#include <rtthread.h>
#include <dfs_fs.h>
#include <dfs_posix.h>
#ifdef RT_USING_MTD_NAND
#include "yaffsfs.h"
#endif

extern const struct romfs_dirent romfs_root;
#define DFS_ROMFS_ROOT          (&romfs_root)

int mount_romfs(void)
{
    if (dfs_mount(NULL, "/", "rom", 0, DFS_ROMFS_ROOT) == 0)
    {
        rt_kprintf("ROMFS File System initialized!\n");
    }
    else
    {
        rt_kprintf("ROMFS File System initialized Failed!\n");
        return -RT_ERROR;
    }
    return RT_EOK;
}
#ifdef RT_USING_MTD_NAND
int mount_nand_yaffs2(void)
{
    rt_err_t result = RT_EOK;
    rt_mtd_nand_t mtd_dev = RT_NULL;

    mtd_dev = (rt_mtd_nand_t)rt_device_find("mt29f");
    if (mtd_dev == RT_NULL)
    {
        rt_kprintf("no mtd device found\n");
        return -RT_ENOSYS;
    }

    yaffs_start_up();

    result = dfs_mount(mtd_dev->parent.parent.name, "/usr", "yaffs", 0, 0);
    if (result == RT_EOK)
    {
        rt_kprintf("Mount YAFFS2 on NAND successfully\n");
    }
    else
    {
        result = dfs_mkfs("yaffs", mtd_dev->parent.parent.name);
        if (result == RT_EOK)
        {
            result = dfs_mount(mtd_dev->parent.parent.name, "/usr", "yaffs", 0, 0);
        }
        else
        {
            rt_kprintf("Mount YAFFS2 on NAND failed\n");
            return -RT_ERROR;
        }
        rt_kprintf("Mount YAFFS2 on NAND successfully\n");
    }
//    if (result == RT_EOK)
//    {
//        struct stat l_stat;
//        result = stat("/mnt/sda1", &l_stat);
//        if ((result == RT_EOK) && (S_ISDIR(l_stat.st_mode))) {
//        } else {
//            result = mkdir("/mnt/sda1", O_CREAT);
//        }
//    }

    return RT_EOK;
}
#endif
#if defined(BSP_USING_SPI_FLASH)

#ifdef PKG_USING_LITTLEFS
int mount_25qx_lfs(void)
{
    rt_err_t result = RT_EOK;
    rt_device_t nor_dev = RT_NULL;
    struct statfs stat;

    nor_dev = (rt_device_t)rt_device_find("data");
    if (nor_dev == RT_NULL)
    {
        rt_kprintf("no GD25Q128 data partition found\n");
        return -RT_ENOSYS;
    }
    if (nor_dev->type != RT_Device_Class_MTD) {
        rt_kprintf("not a MTD device\n");
        return -RT_ENOSYS;
    }

    result = dfs_mount(nor_dev->parent.name, "/var", "lfs", 0, 0);
    if (result == RT_EOK)
    {
        rt_kprintf("Mount lfs on GD25Q128 data partition successfully\n");
    }
    else
    {
        rt_kprintf("Mount fs err. mkfs first\n");
        result = dfs_mkfs("lfs", nor_dev->parent.name);
        if (result == RT_EOK)
        {
            rt_kprintf("Mkfs ok, try mount again\n");
            result = dfs_mount(nor_dev->parent.name, "/var", "lfs", 0, 0);
        }
        else
        {
            rt_kprintf("reMount failed\n");
            return -RT_ERROR;
        }
        rt_kprintf("reMount successfully\n");
    }

    return RT_EOK;
}
#else   // PKG_USING_LITTLEFS
int mount_25qx_vfat(void)
{
    rt_err_t result = RT_EOK;
    rt_device_t nor_dev = RT_NULL;
    struct statfs stat;

    nor_dev = (rt_device_t)rt_device_find("data");
    if (nor_dev == RT_NULL)
    {
        rt_kprintf("no GD25Q128 found\n");
        return -RT_ENOSYS;
    }
    if (nor_dev->type != RT_Device_Class_Block) {
        rt_kprintf("not a Block device\n");
        return -RT_ENOSYS;
    }

    result = dfs_mount(nor_dev->parent.name, "/var", "elm", 0, 0);
    if (result == RT_EOK)
    {
        rt_kprintf("Mount elm on GD25Q128 successfully\n");
    }
    else
    {
        rt_kprintf("Mount fs err. mkfs first\n");
        result = dfs_mkfs("elm", nor_dev->parent.name);
        if (result == RT_EOK)
        {
            rt_kprintf("Mkfs ok, try mount again\n");
            result = dfs_mount(nor_dev->parent.name, "/var", "elm", 0, 0);
        }
        else
        {
            rt_kprintf("reMount failed\n");
            return -RT_ERROR;
        }
        rt_kprintf("reMount successfully\n");
    }

    return RT_EOK;
}
#endif  // PKG_USING_LITTLEFS

#endif  // BSP_USING_SPI_FLASH
int mount_all_fs(void)
{
    if (mount_romfs() == RT_EOK) {
#ifdef RT_USING_MTD_NAND
        mount_nand_yaffs2();
#endif
#if defined(BSP_USING_SPI_FLASH)
#ifdef PKG_USING_LITTLEFS
        mount_25qx_lfs();
#else
        mount_25qx_vfat();
#endif
#endif
    }
    
    return RT_EOK;
}
INIT_ENV_EXPORT(mount_all_fs);
